package ext.tianma.changeManager.util;

import java.sql.Blob;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import org.apache.commons.lang.StringUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import wt.doc.WTDocument;
import wt.fc.ObjectReference;
import wt.fc.Persistable;
import wt.fc.PersistenceHelper;
import wt.fc.QueryResult;
import wt.fc.collections.WTHashSet;
import wt.part.WTPart;
import wt.part.WTPartMaster;
import wt.query.ArrayExpression;
import wt.query.ClassAttribute;
import wt.query.QueryException;
import wt.query.QuerySpec;
import wt.query.SearchCondition;
import wt.util.WTException;
import wt.util.WTPropertyVetoException;
import wt.vc.views.View;
import wt.vc.views.ViewHelper;
import ext.tianma.changeManager.constants.ChangeConstants;
import ext.tianma.changeManager.service.ChangeService;
import ext.tianma.changeManager.vo.ChangeVO;
import ext.tianma.model.RDPBOMModel;
import ext.tianma.model.RDPChange;
import ext.tianma.model.TMECOITEMModel;
import ext.tianma.number.util.PartUtil;
import ext.tianma.util.TMUtil;

/**
 * 类名: QueryUtil </br>
 * 包名: ext.tianma.changeManager.util
 * 描述: 查询对象实体
 * @author xucr
 * 创建时间: 2020年12月1日
 * 发布版本: V1.0
 */
public class QueryUtil {

	private static final Logger logger = LoggerFactory.getLogger(QueryUtil.class);
	/**
	 * 查询指定类型文档
	 * @param params
	 * @return
	 * @author xucr
	 * @CreateDate 2020年11月30日
	 */
	public static QuerySpec queryWTDocument(JSONObject params)  {
		QuerySpec qs = null;
		try {
			qs = new QuerySpec();
			int d = qs.appendClassList(WTDocument.class, true);
		    qs.setAdvancedQueryEnabled(true);
		    
		    //最新小版本
			SearchCondition sc1 = new SearchCondition(WTDocument.class,"iterationInfo.latest", SearchCondition.IS_TRUE, true);
			qs.appendWhere(sc1, new int[] { d });
		    
			//指定小类
			String softType = ChangeUtil.getJSONString(params, "softType");
			if(StringUtils.isNotEmpty(softType)) {
				String [] softTypes = {softType};
				List<Long> branchIds = ChangeUtil.getChildTypeBranchId(softTypes, true);
				Long[] ids = new Long[branchIds.size()];
				SearchCondition sc2 = new SearchCondition(new ClassAttribute(
						WTDocument.class, "typeDefinitionReference.key.branchId"), SearchCondition.IN, new ArrayExpression(branchIds.toArray(ids)));
				qs.appendAnd();
				qs.appendWhere(sc2, new int[] { d });
			}
			
			//编码
			String docNumber = ChangeUtil.getJSONString(params, "docNumber");
			if(StringUtils.isNotEmpty(docNumber)) {
				SearchCondition sc3 = new SearchCondition(WTDocument.class, WTDocument.NUMBER, SearchCondition.EQUAL, docNumber);
				qs.appendAnd();
				qs.appendWhere(sc3, new int[] { d });
			}
			
			//名称
			String docName = ChangeUtil.getJSONString(params, "docName");
			if(StringUtils.isNotEmpty(docName)) {
				SearchCondition sc4 = new SearchCondition(WTDocument.class, WTDocument.NAME, SearchCondition.EQUAL, docName);
				qs.appendAnd();
				qs.appendWhere(sc4, new int[] { d });
			}
			
			//状态
			String states = ChangeUtil.getJSONString(params, "states");
			if(StringUtils.isNotEmpty(states)) {
				SearchCondition sc4 = new SearchCondition(new ClassAttribute(
						WTDocument.class, "state.state"), SearchCondition.IN, new ArrayExpression(states.split(",")));
				qs.appendAnd();
				qs.appendWhere(sc4, new int[] { d });
			}
		} catch (QueryException e) {
			e.printStackTrace();
		} catch (JSONException e) {
			e.printStackTrace();
		}
	    return qs;
	}
	
	/**
	 * 根据rdpid、对象查询变更数据
	 * @param per
	 * @param rdpId
	 * @return
	 * @author xucr
	 * @CreateDate 2020年12月1日
	 */
	public static RDPChange findRDPChange(Persistable per, String rdpId, String module) {
		/**
		 * 一个RDPID 下， 某个模块下，一个物料只会有一条变更信息
		 * */
		JSONObject params = new JSONObject();
		RDPChange change = null;
		try {
			if(null != per && StringUtils.isNotEmpty(rdpId)) {
				params.put("persistableId", per.getPersistInfo().getObjectIdentifier().getId());
				params.put("module", module);
				QuerySpec qs = queryRDPChange(rdpId, params);
				QueryResult qr = PersistenceHelper.manager.find(qs);
				while(qr.hasMoreElements()) {
					change = (RDPChange) qr.nextElement();
					break;
				}
			}
		} catch (JSONException e) {
			e.printStackTrace();
		} catch (WTException e) {
			e.printStackTrace();
		}
		return change;
	}
	
	/**
	 * 获取变更的数据
	 * @param rdpId
	 * @param oid
	 * @return
	 * @author xucr
	 * @CreateDate 2020年12月1日
	 */
	public static JSONObject getRDPChangeData(String rdpId, String oid, String module) {
		JSONObject result = null;
		if(StringUtils.isNotEmpty(rdpId) && StringUtils.isNotEmpty(oid)) {
			Persistable per = TMUtil.oid2Obj(oid);
			RDPChange change = findRDPChange(per, rdpId, module);
			try {
				if(null != change) {
					Blob blob = change.getChangeInfo();
					String str = ChangeUtil.blob2str(blob);
					result = new JSONObject(str);
				}
			} catch (JSONException e) {
				e.printStackTrace();
			}
		}
		return result;
	}
	
	/**
	 * 查询变更信息
	 * @param params
	 * @author xucr
	 * @CreateDate 2020年11月30日
	 */
	public static QuerySpec queryRDPChange(String rdpId, JSONObject params) {
		QuerySpec qs = null;
		try {
			qs = new QuerySpec(RDPChange.class);
		    qs.setAdvancedQueryEnabled(true);
		    //rdpId
		    SearchCondition sc1 = new SearchCondition(RDPChange.class, RDPChange.RDP_ID, SearchCondition.EQUAL, rdpId);
		    qs.appendWhere(sc1, new int[] { 0 });
		    
		    //关联对象（部件、文档）的Id
		    String persistableId = ChangeUtil.getJSONString(params, "persistableId");
		    if(StringUtils.isNotEmpty(persistableId)) {
		    	Long id = Long.valueOf(persistableId);
		    	SearchCondition sc2 = new SearchCondition(RDPChange.class, "persistable.key.id", SearchCondition.EQUAL, id);
		    	qs.appendAnd();
		    	qs.appendWhere(sc2, new int[] { 0 });
		    }
		    
		    //RDP模块
		    String module = ChangeUtil.getJSONString(params, "module");
		    if(StringUtils.isNotEmpty(module)) {
		    	SearchCondition sc3 = new SearchCondition(RDPChange.class, RDPChange.MODULE, SearchCondition.EQUAL, module);
		    	qs.appendAnd();
		    	qs.appendWhere(sc3, new int[] { 0 });
		    }
		    
		    //status
		    String status = ChangeUtil.getJSONString(params, "status");
		    if(StringUtils.isNotEmpty(status)) {
				SearchCondition sc4 = new SearchCondition(new ClassAttribute(
						RDPChange.class, RDPChange.STATUS), SearchCondition.IN, new ArrayExpression(status.split(",")));
				qs.appendAnd();
		    	qs.appendWhere(sc4, new int[] { 0 });
		    }
		    logger.info("queryRDPChange qs >>>" + qs.toString());
		} catch (QueryException e) {
			e.printStackTrace();
		} catch (JSONException e) {
			e.printStackTrace();
		}
		return qs;
	}
	
	/**
	 * 查询RDP_BOM操作数据
	 * @param params
	 * @return
	 * @author xucr
	 * @CreateDate 2020年12月2日
	 */
	public static QuerySpec queryRDPBOMModel(String rdpId, JSONObject params) {
		QuerySpec qs = null;
		try {
			qs = new QuerySpec(RDPBOMModel.class);
		    qs.setAdvancedQueryEnabled(true);
	    	SearchCondition sc1 = new SearchCondition(RDPBOMModel.class, RDPBOMModel.RDP_ID, SearchCondition.EQUAL, rdpId);
	    	qs.appendWhere(sc1, new int[] { 0 });
	    	
	    	//ecooperatingtype
	    	String ecooperatingtype = ChangeUtil.getJSONString(params, "ecooperatingtype");
	    	if(StringUtils.isNotEmpty(ecooperatingtype)) {
	    		SearchCondition sc2 = new SearchCondition(RDPBOMModel.class, RDPBOMModel.ECOOPERATING_TYPE, SearchCondition.EQUAL, ecooperatingtype);
	    		qs.appendAnd();
		    	qs.appendWhere(sc2, new int[] { 0 });
	    	}
	    	
	    	//关联对象（受影响对象）的Id
		    String persistableId = ChangeUtil.getJSONString(params, "persistableId");
		    if(StringUtils.isNotEmpty(persistableId)) {
		    	Long id = Long.valueOf(persistableId);
		    	SearchCondition sc2 = new SearchCondition(RDPBOMModel.class, "ECOAffectedRef.key.id", SearchCondition.EQUAL, id);
		    	qs.appendAnd();
		    	qs.appendWhere(sc2, new int[] { 0 });
		    }
	    	
	    	//status
	    	String status = ChangeUtil.getJSONString(params, "status");
	    	if(StringUtils.isNotEmpty(status)) {
	    		SearchCondition sc3 = new SearchCondition(new ClassAttribute(
	    				RDPBOMModel.class, RDPBOMModel.STATUS), SearchCondition.IN, new ArrayExpression(status.split(",")));
	    		qs.appendAnd();
		    	qs.appendWhere(sc3, new int[] { 0 });
	    	}
	    	logger.info("queryRDPBOMModel qs >>>" + qs.toString());
		} catch (QueryException e) {
			e.printStackTrace();
		} catch (JSONException e) {
			e.printStackTrace();
		}
		return qs;
	}
	
	/**
	 * 按条件查询RDPBOMModel
	 * @param rdpId
	 * @param params
	 * @return
	 * @author xucr
	 * @CreateDate 2020年12月2日
	 */
	public static WTHashSet findRDPBOMModel(String rdpId, JSONObject params) {
		QuerySpec qs = queryRDPBOMModel(rdpId, params);
		WTHashSet set = new WTHashSet();
		try {
			QueryResult qr = PersistenceHelper.manager.find(qs);
			RDPBOMModel model = null;
			while(qr.hasMoreElements()) {
				model = (RDPBOMModel) qr.nextElement();
				set.add(model);
			}
		} catch (WTException e) {
			e.printStackTrace();
		}
		return set;
	}
	
	/**
	 * 根据条件查询rdpchange
	 * @param rdpId
	 * @param params
	 * @return
	 * @author xucr
	 * @CreateDate 2020年12月11日
	 */
	public static WTHashSet findRDPChange(String rdpId, JSONObject params) {
		WTHashSet set = new WTHashSet();
		try {
			QuerySpec qs = queryRDPChange(rdpId, params);
			QueryResult qr = PersistenceHelper.manager.find(qs);
			RDPChange change = null;
			while(qr.hasMoreElements()) {
				change = (RDPChange) qr.nextElement();
				set.add(change);
			}
		} catch (WTException e) {
			e.printStackTrace();
		}
		return set;
	}
	
	/**
	 * 单个保存RDP信息
	 * @param changeData
	 * @param rdpId
	 * @param oid
	 * @param module RDP模块名称
	 * @author xucr
	 * @CreateDate 2020年11月30日
	 */
	public static RDPChange saveRDPChange(ChangeVO vo) {
		RDPChange change = newRDPChange(vo);
		try {
			change = (RDPChange) PersistenceHelper.manager.save(change);
		} catch (WTException e) {
			e.printStackTrace();
		}
		return change;
	}
	
	/**
	 * new一个RDPChange
	 * @param changeData
	 * @param rdpId
	 * @param per
	 * @param module
	 * @return
	 * @author xucr
	 * @CreateDate 2020年12月11日
	 */
	public static RDPChange newRDPChange(ChangeVO vo) {
		RDPChange change = null;
		try {
			change = RDPChange.newRDPChange();
			if(ChangeConstants.RDP_MODULE[0].equals(vo.getModule())) { //仅物料变更时，保存变更数据
				Blob blob = ChangeUtil.str2Blob(vo.getChangeData());
				change.setChangeInfo(blob);
			}
			change.setRdpId(vo.getRdpId());
			change.setPersistable(ObjectReference.newObjectReference(vo.getPer()));
			change.setModule(vo.getModule());
			change.setStatus(ChangeService.OPEN);
			change.setOwner(vo.getOwner());
			change.setCreator(vo.getCreator());
		} catch (WTPropertyVetoException e) {
			e.printStackTrace();
		} catch (WTException e) {
			e.printStackTrace();
		}
		return change;
	}
	
	/**
	 * 查询部件
	 * @param partname
	 * @param partNumber
	 * @return
	 * @throws WTException
	 * @author xucr
	 * @CreateDate 2020年12月1日
	 */
	public static WTPart getWTPartByName(String partname, String partNumber) throws WTException {
		WTPart part = null;
		QueryResult qr = null;
		JSONObject params = new JSONObject();
		try {
			params.put("name", partname);
			params.put("name", partname);
			QuerySpec qs = queryWTPart(params);
			qr = PersistenceHelper.manager.find(qs);
			while (qr.hasMoreElements()) {
				part = (WTPart) qr.nextElement();
				break;
			}
			part = PartUtil.getLatestPartByPartMaster((WTPartMaster) part.getMasterReference().getObject());
		} catch (JSONException e) {
			e.printStackTrace();
		}
		return part;
	}
	
	public static List<WTPart> getAllWTPartByName(String partname, String partNumber) throws WTException {
		QueryResult qr = null;
		JSONObject params = new JSONObject();
		List<WTPart> parts = new ArrayList<WTPart>();
		try {
			params.put("name", partname);
			params.put("number", partNumber);
			QuerySpec qs = queryWTPart(params);
			qr = PersistenceHelper.manager.find(qs);
			WTPart part = null;
			while (qr.hasMoreElements()) {
				part = (WTPart) qr.nextElement();
				parts.add(part);
			}
		} catch (JSONException e) {
			e.printStackTrace();
		}
		return parts;
	}
	
	public static QuerySpec queryWTPart(JSONObject params) throws WTException, JSONException {
		QuerySpec qs = null;
		qs = new QuerySpec(WTPart.class);
		
		//最新小版本
		SearchCondition sc = new SearchCondition(WTPart.class,"iterationInfo.latest", SearchCondition.IS_TRUE, true);
		qs.appendWhere(sc, new int[] { 0 });
		
		// 名称
		String name = ChangeUtil.getJSONString(params, "name");
		if(StringUtils.isNotEmpty(name)) {
			SearchCondition sc1 = new SearchCondition(WTPart.class, WTPart.NAME, SearchCondition.EQUAL, name);
			qs.appendAnd();
			qs.appendWhere(sc1, new int [] {0});
		}
		
		// 编码
		String number = ChangeUtil.getJSONString(params, "number");
		if(StringUtils.isNotEmpty(number)) {
			SearchCondition sc2 = new SearchCondition(WTPart.class, WTPart.NUMBER, SearchCondition.EQUAL, number);
			qs.appendAnd();
			qs.appendWhere(sc2, new int [] {0});
		}
		
		//视图
		String viewName = ChangeUtil.getJSONString(params, "view");
		if(StringUtils.isNotEmpty(viewName)) {
			View view = ViewHelper.service.getView(viewName);
			Long viewId = view.getPersistInfo().getObjectIdentifier().getId();
			SearchCondition sc3 = new SearchCondition(WTPart.class, "view.key.id", SearchCondition.EQUAL, viewId);
			qs.appendAnd();
			qs.appendWhere(sc3, new int [] {0});
		}
		
		return qs;
	}
	
	/**
	 * 判断受影响对象是否在BOM组ECO变更流程中
	 * @param part
	 * @return
	 * @author xucr
	 * @CreateDate 2020年12月3日
	 */
	public static boolean isProcessind(WTPart part) {
		boolean isProcessind = false;
		if(null != part) {
			try {
				/**
				 * 条件：受影响对象、eco状态为open
				 * */
				QuerySpec qs = new QuerySpec(TMECOITEMModel.class);
				SearchCondition sc1 = new SearchCondition(
						TMECOITEMModel.class, "ECOAffectedRef.key.id", SearchCondition.EQUAL, part.getPersistInfo().getObjectIdentifier().getId());
				qs.appendWhere(sc1, new int [] {0});
				SearchCondition sc2 = new SearchCondition(
						TMECOITEMModel.class, TMECOITEMModel.ECOSTATUS, SearchCondition.EQUAL, ChangeService.OPEN);
				qs.appendAnd();
				qs.appendWhere(sc2, new int [] {0});
				QueryResult qr = PersistenceHelper.manager.find(qs);
				if(qr.size() > 0) {
					isProcessind = true;
				}
			} catch (QueryException e) {
				e.printStackTrace();
			} catch (WTException e) {
				e.printStackTrace();
			}
		}
		return isProcessind;
	}
	
	public static JSONObject findProcessStatus(String rdpId, String status) {
		JSONObject result = null;
		try {
			JSONObject params = new JSONObject();
			params.put("status", status);
			
			QuerySpec qs1 = queryRDPChange(rdpId, params);
			QueryResult qr1 = PersistenceHelper.manager.find(qs1);
			
			QuerySpec qs2 = queryRDPBOMModel(rdpId, params);
			QueryResult qr2 = PersistenceHelper.manager.find(qs2);
			
			JSONArray doc1Array = new JSONArray();
			JSONArray doc2Array = new JSONArray();
			JSONArray partArray = new JSONArray();
			JSONArray bomArray = new JSONArray();
			
			while(qr1.hasMoreElements()) {
				initProcessStatus((Persistable) qr1.nextElement(), doc1Array, doc2Array, partArray, bomArray);
			}
			
			while(qr2.hasMoreElements()) {
				initProcessStatus((Persistable) qr2.nextElement(), doc1Array, doc2Array, partArray, bomArray);
			}
			
			JSONArray array = new JSONArray();
			JSONObject obj1 = arrayInfo("工艺文件", doc1Array);
			JSONObject obj2 = arrayInfo("图档类文档", doc2Array);
			JSONObject obj3 = arrayInfo("物料修改", partArray);
			JSONObject obj4 = arrayInfo("BOM变更", bomArray);
			
			array.put(obj1);
			array.put(obj2);
			array.put(obj3);
			array.put(obj4);
			
			result = ChangeUtil.resSuccess(array, array.length());
		} catch (WTException e) {
			e.printStackTrace();
			result = ChangeUtil.resFailed(e.getLocalizedMessage(Locale.getDefault()));
			
		} catch (JSONException e) {
			e.printStackTrace();
			result = ChangeUtil.resFailed(e.getLocalizedMessage());
		}
		return result;
	}
	
	private static void initProcessStatus(Persistable per, JSONArray doc1Array, 
			JSONArray doc2Array, JSONArray partArray, JSONArray bomArray) throws JSONException {
		String status = "";
		String number = "";
		JSONObject obj = null;
		
		if(per instanceof RDPChange) {
			//工艺文件、图档类文档、物料编码进阶
			RDPChange change = (RDPChange) per;
			status = change.getStatus();
			Persistable changePer = change.getPersistable().getObject();
			if(changePer instanceof WTDocument) {
				WTDocument doc = (WTDocument)changePer;
				number = doc.getNumber();
				String softType = ChangeUtil.getSoftTypeName(doc, false);
				if(softType.indexOf(ChangeConstants.DOCTYPES[0]) > -1) { //工艺文档
					obj = processInfo(number, status);
					doc1Array.put(obj);
				} else if(softType.indexOf(ChangeConstants.DOCTYPES[1]) > -1) {//图档类
					obj = processInfo(number, status);
					doc2Array.put(obj);
				}
			} else if(changePer instanceof WTPart) {
				WTPart part = (WTPart) changePer;
				number = part.getNumber();
				obj = processInfo(number, status);
				partArray.put(obj);
			}
		} else if(per instanceof RDPBOMModel) {
			//BOM 变更
			RDPBOMModel model = (RDPBOMModel) per;
			status = model.getStatus();
			obj = processInfo(model.getECOPartNumber(), status);
			bomArray.put(obj);
		}
	}
	
	private static JSONObject processInfo(String number, String status) throws JSONException {
		JSONObject obj = new JSONObject();
		obj.put("number", number);
		obj.put("status", status);
		obj.put("msg", "流程及审批对象已被废弃");//因为各自流程在废弃时，均会废弃评审对象
		return obj;
	}
	
	private static JSONObject arrayInfo(String name, JSONArray array) throws JSONException {
		JSONObject obj1 = new JSONObject();
		obj1.put("name", name);
		obj1.put("detail", array);
		return obj1;
	}
}
